/*
 * MainView.java
 */
package gov.nist.ssd.swqb.gui;

import gov.nist.ssd.swqb.core.exceptions.TimeoutException;
import gov.nist.ssd.swqb.events.ChangeDisplayCountEvent;
import gov.nist.ssd.swqb.events.NewSearchEvent;
import gov.nist.ssd.swqb.events.SearchNewResultEvent;
import gov.nist.ssd.swqb.events.SearchResultEvent;
import gov.nist.ssd.swqb.events.SelectEvent;
import gov.nist.ssd.swqb.events.SetFocusEvent;
import gov.nist.ssd.swqb.events.StopEvent;
import gov.nist.ssd.swqb.gui.boxes.PrefixBox;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.RDFNode;
import gov.nist.ssd.swqb.commands.ChangeDisplayCount;
import gov.nist.ssd.swqb.commands.CommandManager;
import gov.nist.ssd.swqb.commands.NextPage;
import gov.nist.ssd.swqb.commands.PreviousPage;
import gov.nist.ssd.swqb.commands.SetFocus;
import gov.nist.ssd.swqb.config.DebugMode;
import gov.nist.ssd.swqb.config.RequestsTimeout;
import gov.nist.ssd.swqb.core.ConfigFileManager;
import gov.nist.ssd.swqb.core.Display;
import gov.nist.ssd.swqb.core.files.OptionManager;
import gov.nist.ssd.swqb.core.files.PrefixManager;
import gov.nist.ssd.swqb.core.exceptions.InvalidURIException;
import gov.nist.ssd.swqb.core.exceptions.OutOfBoundsException;
import gov.nist.ssd.swqb.core.files.RecentFileManager;
import gov.nist.ssd.swqb.core.search.Search;
import gov.nist.ssd.swqb.core.search.SearchFactory;
import gov.nist.ssd.swqb.gui.boxes.HelpBox;
import gov.nist.ssd.swqb.gui.boxes.OptionBox;
import gov.nist.ssd.swqb.gui.components.SearchComponent;
import gov.nist.ssd.swqb.gui.components.SearchResult;
import gov.nist.ssd.swqb.gui.components.SearchRunnable;
import gov.nist.ssd.swqb.gui.components.graph.GraphView;
//import gov.nist.ssd.swqb.gui.components.graph.GraphView;
import gov.nist.ssd.swqb.listeners.ChangeDisplayCountListener;
import gov.nist.ssd.swqb.listeners.NewSearchListener;
import gov.nist.ssd.swqb.listeners.SearchNewResultListener;
import gov.nist.ssd.swqb.listeners.SearchResultListener;
import gov.nist.ssd.swqb.listeners.SearchSelectListener;
import gov.nist.ssd.swqb.listeners.SetFocusListener;
import gov.nist.ssd.swqb.listeners.StopListener;
import java.awt.BorderLayout;
import java.util.Map;

import java.util.Set;
import org.jdesktop.application.Action;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.FrameView;
import org.jdesktop.application.TaskMonitor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.EventListener;
import java.util.LinkedHashMap;
import javax.swing.Timer;
import javax.swing.Icon;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

/**
 * The application's main frame.
 */
public class MainView extends FrameView {
    
    public MainView(SingleFrameApplication app) {
        super(app);
        
        initComponents();
        init();
        // status bar initialization - message timeout, idle icon and busy animation, etc
        ResourceMap resourceMap = getResourceMap();
        int messageTimeout = resourceMap.getInteger("StatusBar.messageTimeout");
        messageTimer = new Timer(messageTimeout, new ActionListener() {
            
            @Override
            public void actionPerformed(ActionEvent e) {
                statusMessageLabel.setText("");
            }
        });
        messageTimer.setRepeats(false);
        int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
        for (int i = 0; i < busyIcons.length; i++) {
            busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[" + i + "]");
        }
        busyIconTimer = new Timer(busyAnimationRate, new ActionListener() {
            
            @Override
            public void actionPerformed(ActionEvent e) {
                busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
                statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
            }
        });
        idleIcon = resourceMap.getIcon("StatusBar.idleIcon");
        statusAnimationLabel.setIcon(idleIcon);
        progressBar.setVisible(false);

        // connecting action tasks to status bar via TaskMonitor
        TaskMonitor taskMonitor = new TaskMonitor(getApplication().getContext());
        taskMonitor.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            
            @Override
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                String propertyName = evt.getPropertyName();
                if ("started".equals(propertyName)) {
                    if (!busyIconTimer.isRunning()) {
                        statusAnimationLabel.setIcon(busyIcons[0]);
                        busyIconIndex = 0;
                        busyIconTimer.start();
                    }
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(true);
                } else if ("done".equals(propertyName)) {
                    busyIconTimer.stop();
                    statusAnimationLabel.setIcon(idleIcon);
                    progressBar.setVisible(false);
                    progressBar.setValue(0);
                } else if ("message".equals(propertyName)) {
                    String text = (String) (evt.getNewValue());
                    statusMessageLabel.setText((text == null) ? "" : text);
                    messageTimer.restart();
                } else if ("progress".equals(propertyName)) {
                    int value = (Integer) (evt.getNewValue());
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(false);
                    progressBar.setValue(value);
                }
            }
        });
    }
    
    @Action
    public void showAboutBox() {
        if (aboutBox == null) {
            JFrame mainFrame = Main.getApplication().getMainFrame();
            aboutBox = new AboutBox(mainFrame);
            aboutBox.setLocationRelativeTo(mainFrame);
        }
        Main.getApplication().show(aboutBox);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        mainPanel = new javax.swing.JPanel();
        jPanel1 = new javax.swing.JPanel();
        jSeparator2 = new javax.swing.JSeparator();
        jPanel2 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        displayCountField = new javax.swing.JFormattedTextField();
        changeDisplayCountButton = new javax.swing.JButton();
        jSeparator3 = new javax.swing.JSeparator();
        searchPanel = new javax.swing.JPanel();
        centerPanel = new javax.swing.JPanel();
        graphPanel = new javax.swing.JPanel();
        menuBar = new javax.swing.JMenuBar();
        javax.swing.JMenu fileMenu = new javax.swing.JMenu();
        openItem = new javax.swing.JMenuItem();
        recentFilesMenuItem = new javax.swing.JMenu();
        jSeparator1 = new javax.swing.JPopupMenu.Separator();
        javax.swing.JMenuItem exitMenuItem = new javax.swing.JMenuItem();
        editMenu = new javax.swing.JMenu();
        undoMenuItem = new javax.swing.JMenuItem();
        redoMenuItem = new javax.swing.JMenuItem();
        jSeparator4 = new javax.swing.JPopupMenu.Separator();
        nextPageMenuItem = new javax.swing.JMenuItem();
        previousPageMenuItem = new javax.swing.JMenuItem();
        findMenuItem = new javax.swing.JMenuItem();
        editPrefixMenuItem = new javax.swing.JMenuItem();
        jMenu1 = new javax.swing.JMenu();
        optionMenuItem = new javax.swing.JMenuItem();
        javax.swing.JMenu helpMenu = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem();
        statusPanel = new javax.swing.JPanel();
        statusMessageLabel = new javax.swing.JLabel();
        statusAnimationLabel = new javax.swing.JLabel();
        progressBar = new javax.swing.JProgressBar();
        jOptionPane1 = new javax.swing.JOptionPane();

        mainPanel.setMinimumSize(new java.awt.Dimension(600, 400));
        mainPanel.setName("mainPanel"); // NOI18N
        mainPanel.setPreferredSize(new java.awt.Dimension(700, 400));
        mainPanel.setRequestFocusEnabled(false);
        mainPanel.setLayout(new java.awt.BorderLayout());

        jPanel1.setName("jPanel1"); // NOI18N
        jPanel1.setLayout(new java.awt.BorderLayout());

        jSeparator2.setName("jSeparator2"); // NOI18N
        jPanel1.add(jSeparator2, java.awt.BorderLayout.SOUTH);

        jPanel2.setName("jPanel2"); // NOI18N
        jPanel2.setLayout(new java.awt.GridBagLayout());

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance().getContext().getResourceMap(MainView.class);
        jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N
        jLabel1.setName("jLabel1"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 5);
        jPanel2.add(jLabel1, gridBagConstraints);

        displayCountField.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(java.text.NumberFormat.getIntegerInstance())));
        displayCountField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        displayCountField.setText(resourceMap.getString("displayCountField.text")); // NOI18N
        displayCountField.setName("displayCountField"); // NOI18N
        displayCountField.setPreferredSize(new java.awt.Dimension(40, 25));
        displayCountField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                displayCountFieldActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 5);
        jPanel2.add(displayCountField, gridBagConstraints);

        changeDisplayCountButton.setText(resourceMap.getString("changeDisplayCountButton.text")); // NOI18N
        changeDisplayCountButton.setFocusable(false);
        changeDisplayCountButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        changeDisplayCountButton.setName("changeDisplayCountButton"); // NOI18N
        changeDisplayCountButton.setPreferredSize(new java.awt.Dimension(67, 25));
        changeDisplayCountButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        changeDisplayCountButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                changeDisplayCountButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
        jPanel2.add(changeDisplayCountButton, gridBagConstraints);

        jSeparator3.setOrientation(javax.swing.SwingConstants.VERTICAL);
        jSeparator3.setName("jSeparator3"); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
        gridBagConstraints.weighty = 1.0;
        jPanel2.add(jSeparator3, gridBagConstraints);

        searchPanel.setName("searchPanel"); // NOI18N
        searchPanel.setLayout(new java.awt.BorderLayout());
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 2, 0, 5);
        jPanel2.add(searchPanel, gridBagConstraints);

        jPanel1.add(jPanel2, java.awt.BorderLayout.CENTER);

        mainPanel.add(jPanel1, java.awt.BorderLayout.NORTH);

        centerPanel.setName("centerPanel"); // NOI18N
        centerPanel.setLayout(new java.awt.BorderLayout());

        graphPanel.setName("graphPanel"); // NOI18N
        graphPanel.setLayout(new java.awt.BorderLayout());
        centerPanel.add(graphPanel, java.awt.BorderLayout.CENTER);

        mainPanel.add(centerPanel, java.awt.BorderLayout.CENTER);

        menuBar.setName("menuBar"); // NOI18N

        fileMenu.setText(resourceMap.getString("fileMenu.text")); // NOI18N
        fileMenu.setName("fileMenu"); // NOI18N

        openItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK));
        openItem.setText(resourceMap.getString("openItem.text")); // NOI18N
        openItem.setName("openItem"); // NOI18N
        openItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openItemActionPerformed(evt);
            }
        });
        fileMenu.add(openItem);

        recentFilesMenuItem.setText(resourceMap.getString("recentFilesMenuItem.text")); // NOI18N
        recentFilesMenuItem.setName("recentFilesMenuItem"); // NOI18N
        fileMenu.add(recentFilesMenuItem);

        jSeparator1.setName("jSeparator1"); // NOI18N
        fileMenu.add(jSeparator1);

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance().getContext().getActionMap(MainView.class, this);
        exitMenuItem.setAction(actionMap.get("quit")); // NOI18N
        exitMenuItem.setText(resourceMap.getString("exitMenuItem.text")); // NOI18N
        exitMenuItem.setName("exitMenuItem"); // NOI18N
        fileMenu.add(exitMenuItem);

        menuBar.add(fileMenu);

        editMenu.setText(resourceMap.getString("editMenu.text")); // NOI18N
        editMenu.setName("editMenu"); // NOI18N

        undoMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Z, java.awt.event.InputEvent.CTRL_MASK));
        undoMenuItem.setText(resourceMap.getString("undoMenuItem.text")); // NOI18N
        undoMenuItem.setName("undoMenuItem"); // NOI18N
        undoMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                undoMenuItemActionPerformed(evt);
            }
        });
        editMenu.add(undoMenuItem);

        redoMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Y, java.awt.event.InputEvent.CTRL_MASK));
        redoMenuItem.setText(resourceMap.getString("redoMenuItem.text")); // NOI18N
        redoMenuItem.setName("redoMenuItem"); // NOI18N
        redoMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                redoMenuItemActionPerformed(evt);
            }
        });
        editMenu.add(redoMenuItem);

        jSeparator4.setName("jSeparator4"); // NOI18N
        editMenu.add(jSeparator4);

        nextPageMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_RIGHT, java.awt.event.InputEvent.CTRL_MASK));
        nextPageMenuItem.setText(resourceMap.getString("nextPageMenuItem.text")); // NOI18N
        nextPageMenuItem.setName("nextPageMenuItem"); // NOI18N
        nextPageMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                nextPageMenuItemActionPerformed(evt);
            }
        });
        editMenu.add(nextPageMenuItem);

        previousPageMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_LEFT, java.awt.event.InputEvent.CTRL_MASK));
        previousPageMenuItem.setText(resourceMap.getString("previousPageMenuItem.text")); // NOI18N
        previousPageMenuItem.setName("previousPageMenuItem"); // NOI18N
        previousPageMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                previousPageMenuItemActionPerformed(evt);
            }
        });
        editMenu.add(previousPageMenuItem);

        findMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F, java.awt.event.InputEvent.CTRL_MASK));
        findMenuItem.setText(resourceMap.getString("findMenuItem.text")); // NOI18N
        findMenuItem.setName("findMenuItem"); // NOI18N
        findMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                launchSearch(evt);
            }
        });
        editMenu.add(findMenuItem);

        editPrefixMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_P, java.awt.event.InputEvent.CTRL_MASK));
        editPrefixMenuItem.setText(resourceMap.getString("editPrefixMenuItem.text")); // NOI18N
        editPrefixMenuItem.setName("editPrefixMenuItem"); // NOI18N
        editPrefixMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                editPrefixMenuItemActionPerformed(evt);
            }
        });
        editMenu.add(editPrefixMenuItem);

        menuBar.add(editMenu);

        jMenu1.setText(resourceMap.getString("jMenu1.text")); // NOI18N
        jMenu1.setName("jMenu1"); // NOI18N

        optionMenuItem.setText(resourceMap.getString("optionMenuItem.text")); // NOI18N
        optionMenuItem.setName("optionMenuItem"); // NOI18N
        optionMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                optionMenuItemActionPerformed(evt);
            }
        });
        jMenu1.add(optionMenuItem);

        menuBar.add(jMenu1);

        helpMenu.setText(resourceMap.getString("helpMenu.text")); // NOI18N
        helpMenu.setName("helpMenu"); // NOI18N

        jMenuItem1.setText(resourceMap.getString("jMenuItem1.text")); // NOI18N
        jMenuItem1.setName("jMenuItem1"); // NOI18N
        jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem1ActionPerformed(evt);
            }
        });
        helpMenu.add(jMenuItem1);

        aboutMenuItem.setAction(actionMap.get("showAboutBox")); // NOI18N
        aboutMenuItem.setName("aboutMenuItem"); // NOI18N
        helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        statusPanel.setName("statusPanel"); // NOI18N
        statusPanel.setLayout(new java.awt.BorderLayout());

        statusMessageLabel.setText(resourceMap.getString("statusMessageLabel.text")); // NOI18N
        statusMessageLabel.setName("statusMessageLabel"); // NOI18N
        statusPanel.add(statusMessageLabel, java.awt.BorderLayout.WEST);

        statusAnimationLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        statusAnimationLabel.setText(resourceMap.getString("statusAnimationLabel.text")); // NOI18N
        statusAnimationLabel.setName("statusAnimationLabel"); // NOI18N
        statusPanel.add(statusAnimationLabel, java.awt.BorderLayout.EAST);

        progressBar.setMaximum(1000000);
        progressBar.setDoubleBuffered(true);
        progressBar.setIndeterminate(true);
        progressBar.setName("progressBar"); // NOI18N
        progressBar.setPreferredSize(new java.awt.Dimension(200, 20));
        progressBar.setStringPainted(true);
        statusPanel.add(progressBar, java.awt.BorderLayout.CENTER);

        jOptionPane1.setName("jOptionPane1"); // NOI18N

        setComponent(mainPanel);
        setMenuBar(menuBar);
        setStatusBar(statusPanel);
    }// </editor-fold>//GEN-END:initComponents

private void openItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openItemActionPerformed
    JFrame mainFrame = Main.getApplication().getMainFrame();
    
    int returnVal = fc.showDialog(mainFrame, "Choose data set");
    if (returnVal == JFileChooser.APPROVE_OPTION) {
        this.loadDataset(fc.getSelectedFile().getAbsolutePath());
    }
}//GEN-LAST:event_openItemActionPerformed
    
private void launchSearch(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_launchSearch
    this.searchField.requestFocus();
}//GEN-LAST:event_launchSearch
    
private void changeDisplayCountButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_changeDisplayCountButtonActionPerformed
    changeDisplayCount();
}//GEN-LAST:event_changeDisplayCountButtonActionPerformed
    
    private void editPrefixMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editPrefixMenuItemActionPerformed
        new Thread(
                new Runnable() {
                    
                    @Override
                    public void run() {
                        Model model = null;
                        if (graphView != null && graphView.getDisplay() != null) {
                            model = graphView.getDisplay().getModel();
                        }
                        PrefixBox prefixBox = new PrefixBox(getFrame(), true);
                        Map<String, String> prefix = prefixBox.getPrefix(
                                prefixManager,
                                model);
                        if (prefix == null || prefix.isEmpty()) {
                            return;
                        }
                        
                        Set<String> keySet = prefix.keySet();
                        for (String ns : keySet) {
                            //delete values
                            if (prefix.get(ns) == null) {
                                prefixManager.remove(ns);
                            } else {
                                prefixManager.setPrefix(ns, prefix.get(ns));
                            }
                        }
                        prefixManager.save();
                        if (model != null) {
                            Display display = graphView.getDisplay();
                            RDFNode currentFocus = display.getCurrentFocus();
                            int currentPageIndex = display.getCurrentPageIndex();
                            try {
                                graphView.clear();
                                display.setFocus(currentFocus);
                                display.setPageIndex(currentPageIndex);
                            } catch (TimeoutException ex) {
                                errorDisplayer.displayError("Timeout error");
                            } catch (InvalidURIException ex) {
                                errorDisplayer.displayError("Invalide URI");
                            } catch (OutOfBoundsException ex) {
                                errorDisplayer.displayError("Out of bound exception");
                            }
                        }
                    }
                }).start();
    }//GEN-LAST:event_editPrefixMenuItemActionPerformed
    
private void optionMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_optionMenuItemActionPerformed
    this.optionBox.setVisible(true);
}//GEN-LAST:event_optionMenuItemActionPerformed
    
private void undoMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_undoMenuItemActionPerformed
    commandManager.undo();
}//GEN-LAST:event_undoMenuItemActionPerformed
    
private void redoMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_redoMenuItemActionPerformed
    commandManager.redo();
}//GEN-LAST:event_redoMenuItemActionPerformed
    
private void previousPageMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_previousPageMenuItemActionPerformed
    if (graphView != null && graphView.getDisplay() != null) {
        commandManager.exec(new PreviousPage(graphView.getDisplay()));
    }
}//GEN-LAST:event_previousPageMenuItemActionPerformed
    
private void nextPageMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextPageMenuItemActionPerformed
    if (graphView != null && graphView.getDisplay() != null) {
        commandManager.exec(new NextPage(graphView.getDisplay()));
    }
}//GEN-LAST:event_nextPageMenuItemActionPerformed
    
private void displayCountFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_displayCountFieldActionPerformed
    this.changeDisplayCount();
}//GEN-LAST:event_displayCountFieldActionPerformed

    private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem1ActionPerformed
        HelpBox b = new HelpBox(this.getFrame(), true);
        b.setVisible(true);
    }//GEN-LAST:event_jMenuItem1ActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel centerPanel;
    private javax.swing.JButton changeDisplayCountButton;
    private javax.swing.JFormattedTextField displayCountField;
    private javax.swing.JMenu editMenu;
    private javax.swing.JMenuItem editPrefixMenuItem;
    private javax.swing.JMenuItem findMenuItem;
    private javax.swing.JPanel graphPanel;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JOptionPane jOptionPane1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPopupMenu.Separator jSeparator1;
    private javax.swing.JSeparator jSeparator2;
    private javax.swing.JSeparator jSeparator3;
    private javax.swing.JPopupMenu.Separator jSeparator4;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JMenuItem nextPageMenuItem;
    private javax.swing.JMenuItem openItem;
    private javax.swing.JMenuItem optionMenuItem;
    private javax.swing.JMenuItem previousPageMenuItem;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JMenu recentFilesMenuItem;
    private javax.swing.JMenuItem redoMenuItem;
    private javax.swing.JPanel searchPanel;
    private javax.swing.JLabel statusAnimationLabel;
    private javax.swing.JLabel statusMessageLabel;
    private javax.swing.JPanel statusPanel;
    private javax.swing.JMenuItem undoMenuItem;
    // End of variables declaration//GEN-END:variables
    private GraphView graphView;
    private final Timer messageTimer;
    private final Timer busyIconTimer;
    private final Icon idleIcon;
    private final Icon[] busyIcons = new Icon[15];
    private int busyIconIndex = 0;
    private JDialog aboutBox;
    private OptionBox optionBox;
    private ConfigFileManager configFileManager;
    private PrefixManager prefixManager;
    private OptionManager optionManager;
    private RecentFileManager recentManager;
    private ErrorDisplayer errorDisplayer;
    private JFileChooser fc;
    private CommandManager commandManager;
    private SearchComponent searchField;
    private SearchResult searchResult;
    
    
    private SearchRunnable searchRunnable = null;

    /**
     * Init custome components
     */
    private void init() {
        this.initLookAndFeel();
        this.initFileManagers();
        this.initFileChooser();
        
        this.commandManager = new CommandManager();
        this.graphView = new GraphView(this, commandManager, optionManager);
        
        
        this.graphPanel.add(this.graphView, BorderLayout.CENTER);
        this.optionBox = new OptionBox(this.getFrame(), true, optionManager);
        this.searchField = new SearchComponent();
        this.searchField.setEditable(false);
        this.searchPanel.add(this.searchField, BorderLayout.CENTER);
        
        this.searchResult = new SearchResult();
        this.centerPanel.add(this.searchResult, BorderLayout.EAST);
        
        this.updateRecentFiles();
        
        String defDisplayCount = this.optionManager.getOption("default_display_count");
        if (defDisplayCount != null) {
            this.displayCountField.setText(defDisplayCount);
        }
        
        this.searchField.addSearchResultListener(new SearchResultListener() { 
            @Override
            public void newResult(SearchResultEvent evt) {
                searchResult.setContent(evt.getData());
            }
        });
        
        this.searchField.addNewSearchListener(new NewSearchListener() {

            @Override
            public void newSearch(final NewSearchEvent evt) {
                
                if (searchRunnable != null && searchRunnable.isRunning()) {
                    searchRunnable.stop();
                }
                Thread t = new Thread(new Runnable() {

                    @Override
                    public void run() {
                        Search s = SearchFactory.getSearch(evt.getTxt(), graphView.getDisplay().getModel());
                        //List<RDFNode> result = searchEngine.search(getText());
                        final Map<String, RDFNode> m = new LinkedHashMap<String, RDFNode>();

                        searchRunnable = new SearchRunnable(s);
                        searchRunnable.addSearchNewResultListener(new SearchNewResultListener() {
                            @Override
                            public void newResult(SearchNewResultEvent evt) {
                                searchResult.addContent(evt.getTxt(), evt.getNode());
                            }
                        });
                        searchResult.addStopListener(new StopListener() {

                            @Override
                            public void stop(StopEvent evt) {
                               searchRunnable.stop();
                            }
                        });

                        Thread t2 = new Thread(searchRunnable);
                        t2.start();
                    }
                });
                t.start();
                searchResult.clear();
                searchResult.expand();
            }
        });
        
        this.searchResult.addSearchSelectListener(new SearchSelectListener() {
            
            @Override
            public void selectPerformed(SelectEvent e) {
                commandManager.exec(new SetFocus(graphView.getDisplay(), e.getSelectedNode()));
            }
        });
        
    }
    
    private void initLookAndFeel() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            SwingUtilities.updateComponentTreeUI(this.getFrame());
        } catch (InstantiationException e) {
        } catch (ClassNotFoundException e) {
        } catch (UnsupportedLookAndFeelException e) {
        } catch (IllegalAccessException e) {
        }
    }
    
    private void initFileManagers() {
        //Select os
        String os = System.getProperty("os.name");
        String baseDir = System.getenv("HOME") + "/.swqb/";
        if (os.toLowerCase().contains("windows")) {
            baseDir = System.getenv("APPDATA") + "/Swqb/";
        }
        
        this.errorDisplayer = ErrorDisplayer.getInstance();
        this.errorDisplayer.setDefaultParentFrame(this.getFrame());
        
        this.configFileManager = new ConfigFileManager(baseDir);
        this.prefixManager = new PrefixManager(configFileManager);
        this.optionManager = new OptionManager(configFileManager);
        this.recentManager = new RecentFileManager(configFileManager);

        //Notify debugMode et timeout
        DebugMode.setOptionManager(optionManager);
        RequestsTimeout.setOptionManager(optionManager);
    }
    
    private void initFileChooser() {
        this.fc = new JFileChooser();
        this.fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        //Set default foler if exists
        String defFolder = this.optionManager.getOption("default_folder");
        if (defFolder != null) {
            fc.setCurrentDirectory(new File(defFolder));
        }
    }
    
    protected void updateRecentFiles() {
        this.recentFilesMenuItem.removeAll();
        for (final String i : this.recentManager.getRecentFiles()) {
            JMenuItem recentFileItem = new JMenuItem(i);
            recentFileItem.addActionListener(new ActionListener() {
                
                @Override
                public void actionPerformed(ActionEvent e) {
                    loadDataset(i);
                }
            });
            this.recentFilesMenuItem.add(recentFileItem);
        }
    }
    
    public void setGraphLoadText() {
        this.statusMessageLabel.setText("Generating");
    }
    
    public void setGraphLoad(Integer l, Integer t) {
        this.progressBar.setValue((int) ((this.progressBar.getMaximum() * l.floatValue()) / t.floatValue()));
    }

    /*private-package*/ GraphView getGraphView() {
        return graphView;
    }
    
    PrefixManager getPrefixManager() {
        return this.prefixManager;
    }
    
    private void loadDataset(final String path) {
        if (this.graphView != null && this.graphView.getDisplay() != null) {
            int r = JOptionPane.showConfirmDialog(
                    this.getFrame(),
                    "You have an opened data-set.\n"
                    + "Do you want to close it?",
                    "New data-set",
                    JOptionPane.YES_NO_OPTION);
            if (r == JOptionPane.NO_OPTION) {
                return;
            }
        }
        final MainView t = this;
        new Thread(
                new Runnable() {
                    
                    @Override
                    public void run() {
                        try {
                            int i = Integer.decode(displayCountField.getText());
                            Display dis = new Display(path, prefixManager, i);
                            
                            dis.addSetFocusListener(new SetFocusListener() {
                                
                                @Override
                                public void setFocusStart(SetFocusEvent e) {
                                    progressBar.setVisible(true);
                                    progressBar.setIndeterminate(true);
                                    busyIconTimer.start();
                                }
                                
                                @Override
                                public void setFocusEnd(SetFocusEvent e) {
                                    progressBar.setVisible(false);
                                    busyIconTimer.stop();
                                }
                            }); //Maj view
                            dis.addChangeDisplayCountListener(new ChangeDisplayCountListener() {
                                
                                @Override
                                public void displayCountChanged(ChangeDisplayCountEvent e) {
                                    
                                    displayCountField.setText(Integer.toString(e.getNewCount()));
                                }
                            });

                            graphView.clear();
                            graphView.setDisplay(dis);

                            //Maj search
                            searchField.setEditable(true);

                            //Update recents files
                            recentManager.addFile(path);
                            updateRecentFiles();
                        } catch (Exception ex) {
                            errorDisplayer.displayError("Error while opening the data set : " + path + "\nMessage : " + ex.getMessage(),
                                    ex);
                        }
                    }
                }).start();
    }
    
    private void changeDisplayCount() {
        if (this.graphView != null) {
            int i = Integer.decode(this.displayCountField.getText());
            this.commandManager.exec(new ChangeDisplayCount(this.graphView.getDisplay(), i));
        }
    }
}
